﻿using FNN.Networks;
using System;
using System.Collections.Generic;
using System.Linq;

namespace FNN.Genetic.Managers
{
    public abstract class CrossbreedingManager
    {
        protected Random _randomizer = new Random();

        /// <summary>
        ///     Случайное скрещивание (равномерный закон распределения)
        /// </summary>
        /// <param name="sourceList">Исходный список кандидатов на скрещивание</param>
        /// <returns>Список детей</returns>
        public List<Network> RandomSelection(List<Network> sourceList)
        {
            List<Network> result = new List<Network>();
            Dictionary<Network, Network> crossbreedingPairs = new Dictionary<Network, Network>();

            while (sourceList.Count > 0)
            {
                int firstNetworkIndex = _randomizer.Next(0, sourceList.Count);
                int secondNetworkIndex = _randomizer.Next(0, sourceList.Count);

                while (secondNetworkIndex == firstNetworkIndex)
                {
                    secondNetworkIndex = _randomizer.Next(0, sourceList.Count);
                }

                Network firstNetwork = sourceList.ElementAt(firstNetworkIndex);
                Network secondNetwork = sourceList.ElementAt(secondNetworkIndex);

                crossbreedingPairs.Add(firstNetwork, secondNetwork);
                sourceList.Remove(firstNetwork);
                sourceList.Remove(secondNetwork);
            }

            result = ExecuteCrossbreeding(crossbreedingPairs);

            return result;
        }
        
        /// <summary>
        ///     Скрещивание на основе "качества" кандидатов
        /// </summary>
        /// <param name="sourceList">Исходный список кандидатов на скрещивание</param>
        /// <returns>Список детей</returns>
        public abstract List<Network> AdvancedSelection(List<Network> sourceList);

        /// <summary>
        ///     Запустить процесс скрещивания
        /// </summary>
        /// <param name="sourcePairs">Пары для скрещивания</param>
        /// <returns>Список детей</returns>
        protected abstract List<Network> ExecuteCrossbreeding(Dictionary<Network, Network> sourcePairs);
    }
}
